home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 1.iso / DEMON / RISCOS2 / TCP_131S.ARC / c / Terminal < prev    next >
Text File  |  1994-03-06  |  32KB  |  1,199 lines

  1. /* cu-notic.txt         NCSA Telnet version 2.2C     2/3/89
  2.    Notice:
  3.         Portions of this file have been modified by
  4.         The Educational Resources Center of Clarkson University.
  5.  
  6.         All modifications made by Clarkson University are hereby placed
  7.         in the public domain, provided the following statement remain in
  8.         all source files.
  9.  
  10.         "Portions Developed by the Educational Resources Center, 
  11.                 Clarkson University"
  12.  
  13.         Bugs and comments to bkc@omnigate.clarkson.edu
  14.                                 bkc@clgw.bitnet
  15.  
  16.         Brad Clements
  17.         Educational Resources Center
  18.         Clarkson University
  19. */
  20.  
  21. /*
  22.  *
  23.  *      Virtual Screen Kernel Emulation Routines
  24.  *                      (vsem.c)
  25.  *  
  26.  *   National Center for Supercomputing Applications
  27.  *      by Gaige B. Paulsen
  28.  *
  29.  *    This file contains the private emulation calls for the NCSA
  30.  *  Virtual Screen Kernel.
  31.  *
  32.  *      Version Date    Notes
  33.  *      ------- ------  ---------------------------------------------------
  34.  *      0.01    861102  Initial coding -GBP
  35.  *      0.10    861111  Added/Modified VT emulator -GBP
  36.  *      0.50    861113  First compiled edition -GBP
  37.  *              2.1     871130  NCSA Telnet 2.1 -GBP
  38.  *              2.2     880715  NCSA Telnet 2.2 -GBP
  39.  */
  40. #include <stdio.h>
  41. #include <stdlib.h>
  42. #include <string.h>
  43.  
  44. #include "bbc.h"
  45. #include "global.h"
  46. #include "menu.h"
  47. #include "os.h"
  48. #include "misc.h"
  49. #include "session.h"
  50. #include "sprite.h"
  51. #include "wimp.h"
  52. #include "wimpt.h"
  53. #include "win.h"
  54. #include "dbox.h"
  55. #include "template.h"
  56.  
  57. #include "cmdparse.h"
  58. #include "Terminal.h"
  59.  
  60. /* Adam - 02-Feb-94 */
  61. #include "xferrecv.h"
  62. #include "werr.h"
  63.  
  64.  
  65. #define OS_ChangedBox  0x0000005a
  66.  
  67. BOOL scale = FALSE;
  68.  
  69. typedef struct
  70. {
  71.   int flag;
  72.   wimp_box box;
  73. }
  74. change_box;
  75.  
  76. static void Window_Scroll(Terminal *);
  77. static os_error *Changed_Box(int, change_box **);
  78.  
  79. /* Adam - 02-Feb-94 */
  80. static void Process_Import(wimp_eventstr *Event, Terminal *Window);
  81. static char *leafname(char *s);
  82.  
  83.  
  84. #define XtoWork(x) ((x) << 1)
  85. #define YtoWork(y) ((y) << 2)
  86.  
  87. int keymap(int raw, char *buffer, int c)
  88. {
  89.         if (raw)
  90.         {
  91.                  switch (c)
  92.                  {
  93.                          case 0x181:   /* F1 */
  94.                                strcpy(buffer, "\033OP");
  95.                                return(3);
  96.                          case 0x182:   /* F2 */
  97.                                strcpy(buffer, "\033OQ");
  98.                                return(3);
  99.                          case 0x183:   /* F3 */
  100.                                strcpy(buffer, "\033OR");
  101.                                return(3);
  102.                          case 0x184:   /* F4 */
  103.                                strcpy(buffer, "\033OS");
  104.                                return(3);
  105.                          case 0x1CD:   /* Insert */
  106.                                strcpy(buffer, "\033[1~");
  107.                                return(4);
  108.                          case 0x1E:    /* Home */
  109.                                strcpy(buffer, "\033[2~");
  110.                                return(4);
  111.                          case 0x19F:   /* Page Up */
  112.                                strcpy(buffer, "\033[3~");
  113.                                return(4);
  114.                          case 0x7F:    /* Delete */
  115.                                strcpy(buffer, "\033[4~");
  116.                                return(4);
  117.                          case 0x18B:   /* Copy */
  118.                                strcpy(buffer, "\033[5~");
  119.                                return(4);
  120.                          case 0x19E:   /* Page Down */
  121.                                strcpy(buffer, "\033[6~");
  122.                                return(4);
  123.                          case 0x18F:   /* Up Arrow */
  124.                                strcpy(buffer, "\033[A");
  125.                                return(3);
  126.                          case 0x18E:   /* Down Arrow */
  127.                                strcpy(buffer, "\033[B");
  128.                                return(3);
  129.                          case 0x18D:   /* Right Arrow */
  130.                                strcpy(buffer, "\033[C");
  131.                                return(3);
  132.                          case 0x18C:    /* Left Arrow */
  133.                                strcpy(buffer, "\033[D");
  134.                                return(3);
  135.                          case 0x18A:    /* Tab */
  136.                                strcpy(buffer, "\0x09");
  137.                                return(1);
  138.                          default:
  139.                                if (c < 0x7F)
  140.                                {
  141.                                        *buffer = c;
  142.                                        return(1);
  143.                                }
  144.                                break;
  145.                  }
  146.         }
  147.         else
  148.         {
  149.                  switch (c)
  150.                  {
  151.                          case '\r':
  152.                          case '\n':
  153.                                strcpy(buffer, "\r\n");
  154.                                return(2);
  155.                          default:
  156.                                if (c < 0x7F)
  157.                                {
  158.                                        *buffer = c;
  159.                                        return(1);
  160.                                }
  161.                                break;
  162.                  }
  163.         }
  164.  
  165.         return(0); 
  166. }
  167.  
  168. static void Redo_Window(Terminal *Window, wimp_redrawstr r, BOOL more)
  169. {
  170.   BOOL more_to_do      = more;
  171.   wimp_redrawstr new_r = r;
  172.   sprite_factors  factors;
  173.   sprite_pixtrans pixtrans[256];
  174.  
  175.   wimp_readpixtrans(Window->Sprite.Area, &Window->Sprite.id, &factors, pixtrans);
  176.  
  177.   if (scale)
  178.   {
  179.  
  180.     factors.xdiv *= Window->X_Div_Mult;
  181.     factors.ydiv *= Window->Y_Div_Mult;
  182.     factors.xmag *= Window->X_Mag_Mult;
  183.     factors.ymag *= Window->Y_Mag_Mult;
  184.   }
  185.  
  186.   while (more_to_do)
  187.   {
  188.     if (scale)
  189.       sprite_put_scaled(Window->Sprite.Area, &Window->Sprite.id, 0, r.box.x0, r.box.y0, &factors, pixtrans);
  190.     else
  191.       sprite_put_scaled(Window->Sprite.Area, &Window->Sprite.id, 0, r.box.x0 - r.scx, r.box.y1 - 768 - r.scy, &factors, pixtrans);
  192.  
  193.     wimp_get_rectangle(&new_r, &more_to_do);
  194.   }
  195. }
  196.  
  197. static void Redraw_Window(Terminal *Window, wimp_w handle)
  198. {
  199.   BOOL more;
  200.   wimp_redrawstr r;
  201.   wimp_winfo     winfo;
  202.  
  203.   winfo.w = handle;
  204.   wimp_get_wind_info(&winfo);
  205.  
  206.   Window->X_Div_Mult = winfo.info.ex.x1 - winfo.info.ex.x0;
  207.   Window->Y_Div_Mult = winfo.info.ex.y1 - winfo.info.ex.y0;
  208.   Window->X_Mag_Mult = winfo.info.box.x1 - winfo.info.box.x0;
  209.   Window->Y_Mag_Mult = winfo.info.box.y1 - winfo.info.box.y0;
  210.  
  211.   r.w = handle;
  212.   wimp_redraw_wind(&r, &more);
  213.  
  214.   if (more)
  215.     Redo_Window(Window, r, more);
  216. }
  217.  
  218. static void Open_Window(Terminal *Window, wimp_openstr *o)
  219. {
  220.   if (scale)
  221.   {
  222.     o->x = 0;
  223.     o->y = 0;
  224.   }
  225.  
  226.   wimp_open_wind(o);
  227.  
  228.   if (Window->Old_X != (o->box.x1 - o->box.x0) ||
  229.       Window->Old_Y != (o->box.y1 - o->box.y0))
  230.   {
  231.     Redraw_Window(Window, o->w);
  232.     Window->Old_X = o->box.x1 - o->box.x0;
  233.     Window->Old_Y = o->box.y1 - o->box.y0;
  234.   }
  235. }
  236.  
  237. void Update_Window(Terminal *Window, wimp_redrawstr r)
  238. {
  239.   wimp_redrawstr new_r = r;
  240.   BOOL more;
  241.  
  242.   wimp_update_wind(&new_r, &more);
  243.  
  244.   if (more)
  245.     Redo_Window(Window, new_r, more);
  246. }
  247.  
  248. void Window_Reset(Terminal *Window)
  249. {
  250.   int i;
  251.  
  252.   Window->x      = 0;
  253.   Window->y      = 0;
  254.   Window->Top    = 0;
  255.   Window->Bottom = 23;
  256.   Window->Attr   = ATTR_NORMAL;
  257.   Window->Cursor = 1;
  258.   Window->G0     = 0;
  259.   Window->G1     = 1;
  260.  
  261.   Window->Parmptr = 0;
  262.   for (i = 0; i < 6; i++)
  263.     Window->Parms[i] = -1;
  264.  
  265.   for (i = 0; i < SCREEN_WIDTH; i++)
  266.     Window->Tabs[i] = (i % TAB_STOPS) ? ' ' : 'x';
  267.   Window->Tabs[SCREEN_WIDTH - 1] = 'x';
  268.  
  269.   bbc_vduq(28, 0, 23, 79, 0);
  270.  
  271.   bbc_vduq(17, 128 + Window->Background[ATTR_NORMAL]);
  272.   bbc_vduq(17,       Window->Foreground[ATTR_NORMAL]);
  273.   bbc_cls();
  274. }
  275.  
  276. void Window_Write(Terminal *Window, char *s, int n)
  277. {
  278.   sprite_state State;
  279.   wimp_redrawstr r;
  280.   register int Escflg;
  281.   change_box *Box; 
  282.   int i, cx, cy;
  283.  
  284.   if (Window == NULL)
  285.     return;
  286.   if (Window->Record != NULL)
  287.     fwrite(s, 1, n, Window->Record);
  288.  
  289.   sprite_outputtosprite(Window->Sprite.Area, &Window->Sprite.id, Window->Save_Area, &State);
  290.  
  291.   Changed_Box(1, &Box);
  292.   Changed_Box(2, &Box);
  293.  
  294.   Escflg = Window->Esc_Flag;
  295.  
  296.   if (Window->Cursor)
  297.   {
  298.     cx = Window->x * 16;
  299.     cy = 768 - Window->y * 32 - 28;
  300.     bbc_vduq(25, 4,   cx % 256, cx / 256,
  301.     cy % 256, cy / 256);
  302.     bbc_vduq(25, 102, (cx + 16) % 256, (cx + 16) / 256,
  303.     (cy + 24) % 256, (cy + 24) / 256);
  304.   }
  305.  
  306.   bbc_vduq(17, 128 + Window->Background[ATTR_NORMAL]);
  307.   bbc_vduq(17,       Window->Foreground[ATTR_NORMAL]);
  308.  
  309.   while (n > 0)
  310.   {
  311.     while ((Escflg == ESCAPE_NONE) && (n > 0) && (*s < 32))
  312.     {
  313.       switch (*s)
  314.       {
  315.       case 0x1b:      /* \E ... */
  316.         Escflg = ESCAPE_FOUND;
  317.         break;
  318.       case 0x07:      /* ^G - bel */
  319.         bbc_vdu(7);
  320.         break;
  321.       case 0x08:      /* ^H - cub1 */
  322.         Window->x--;
  323.         Window_Scroll(Window);
  324.         break;
  325.       case 0x0e:
  326.         Window->Charset = 1;
  327.         break;
  328.       case 0x0f:
  329.         Window->Charset = 0;
  330.         break;
  331.       case 0x09:      /* ^I - ht */
  332.         for (i = Window->x + 1; i < SCREEN_WIDTH; i++)
  333.         {      
  334.           if (Window->Tabs[i] == 'x')
  335.           {
  336.             Window->x = i;
  337.             break;
  338.           }
  339.         }
  340.         Window_Scroll(Window);
  341.         break;
  342.       case 0x0d:      /* ^M - cr */
  343.         Window->x = 0;
  344.         bbc_vdu(13);
  345.         break;
  346.       case 0x0a:      /* ^J - lf */
  347.         Window->y++;
  348.         Window->x = 0;
  349.         if (Window->y > Window->Bottom)
  350.           Window->y = Window->Bottom;
  351.         bbc_vdu(10);
  352.         bbc_vdu(13);
  353.         break;
  354.       default:
  355.         break;
  356.       }
  357.  
  358.       s++;
  359.       n--;
  360.     }
  361.  
  362.     bbc_vduq(17, 128 + Window->Background[Window->Attr]);
  363.     bbc_vduq(17,       Window->Foreground[Window->Attr]);
  364.  
  365.     while ((n > 0) && (Escflg == ESCAPE_NONE) && (*s >= 32))
  366.     {
  367.       bbc_vdu(*s);
  368.       Window->x++;
  369.       Window_Scroll(Window);
  370.  
  371.       s++;
  372.       n--;
  373.     }
  374.  
  375.     bbc_vduq(17, 128 + Window->Background[ATTR_NORMAL]);
  376.     bbc_vduq(17,       Window->Foreground[ATTR_NORMAL]);
  377.  
  378.     while ((n > 0) && (Escflg == ESCAPE_FOUND))
  379.     {
  380.       switch (*s)
  381.       {
  382.       case 0x08:
  383.         Window->x--;
  384.         Window_Scroll(Window);
  385.         break;
  386.       case '[':       /* \E[ ... */
  387.         Window->Parmptr = 0;
  388.         for (i = 0; i < 6; i++)
  389.           Window->Parms[i] = -1;
  390.         Escflg = ESCAPE_1;
  391.         break;
  392.       case '7':       /* \E7 - sc */
  393.         Window->Save_x    = Window->x;
  394.         Window->Save_y    = Window->y;
  395.         Window->Save_Attr = Window->Attr;
  396.         Escflg = ESCAPE_NONE;
  397.         break;
  398.       case '8':       /* \E8 - rc */
  399.         Window->x    = Window->Save_x;
  400.         Window->y    = Window->Save_y;
  401.         Window->Attr = Window->Save_Attr;
  402.         Escflg = ESCAPE_NONE;
  403.         break;
  404.       case 'c':       /* \Ec ... */
  405.         Window_Reset(Window);
  406.         Escflg = ESCAPE_NONE;
  407.         break;
  408.       case 'D':       /* \ED */
  409.         Window->y++;
  410.         Window_Scroll(Window);
  411.         Escflg = ESCAPE_NONE;
  412.         break;
  413.       case 'E':       /* \EE */
  414.         Window->y++;
  415.         Window->x = 0;
  416.         Window_Scroll(Window);
  417.         Escflg = ESCAPE_NONE;
  418.         break;
  419.       case 'M':       /* \EM - ri */
  420.         Window->y--;
  421.         Window_Scroll(Window);
  422.         Escflg = ESCAPE_NONE;
  423.         break;
  424.       case '>':       /* \E> - rmkx */
  425.         if (Window->Session)
  426.           Window->Session->keypad = 0;
  427.         else
  428.           Window->keypad = 0;
  429.         Escflg = ESCAPE_NONE;
  430.         break;
  431.       case '=':       /* \E= - smkx */
  432.         if (Window->Session)
  433.           Window->Session->keypad = 1;
  434.         else
  435.           Window->keypad = 1;
  436.         Escflg = ESCAPE_NONE;
  437.         break;
  438.       case '(':       /* \E( ... */
  439.         Escflg = ESCAPE_3;
  440.         break;
  441.       case ')':       /* \E) ... */
  442.         Escflg = ESCAPE_4;
  443.         break;
  444.       case '#':       /* \E# ... */
  445.         Escflg = ESCAPE_5;
  446.         break;
  447.       case 'H':       /* \EH - hts */
  448.         Window->Tabs[Window->x] = 'x';
  449.         Escflg = ESCAPE_NONE;
  450.         break;
  451.       default:
  452.         Escflg = ESCAPE_NONE;
  453.         break;
  454.       }
  455.  
  456.       s++;
  457.       n--;
  458.     }
  459.  
  460.     while ((Escflg == ESCAPE_1) && (n > 0))
  461.     {
  462.       switch (*s)
  463.       {
  464.       case 0x08:
  465.         Window->x--;
  466.         Window_Scroll(Window);
  467.         break;
  468.       case '0':
  469.       case '1':
  470.       case '2':
  471.       case '3':
  472.       case '4':
  473.       case '5':
  474.       case '6':
  475.       case '7':
  476.       case '8':
  477.       case '9':
  478.         if (Window->Parms[Window->Parmptr] < 0) Window->Parms[Window->Parmptr] = 0;
  479.         Window->Parms[Window->Parmptr] *= 10;
  480.         Window->Parms[Window->Parmptr] += *s - '0';
  481.         break;
  482.       case '?':       /* \E[? ... */
  483.         Window->Parms[Window->Parmptr++] = -2;
  484.         break;
  485.       case ';':       /* \E[nn; ... */
  486.         Window->Parmptr++;
  487.         break;
  488.       case 'A':       /* \E[%p1%dA - cuu, cuu1 */
  489.         if (Window->Parms[0] < 1)
  490.           Window->y--;
  491.         else
  492.             Window->y -= Window->Parms[0];
  493.         Window_Scroll(Window);
  494.         Escflg = ESCAPE_NONE;
  495.         break;
  496.       case 'B':       /* \E[%p1%dB - cud */
  497.         if (Window->Parms[0] < 1)
  498.           Window->y++;
  499.         else
  500.             Window->y += Window->Parms[0];
  501.         Window_Scroll(Window);
  502.         Escflg = ESCAPE_NONE;
  503.         break;
  504.       case 'C':       /* \E[%p1%dC - cuf, cuf1 */
  505.         if (Window->Parms[0] < 1)
  506.           Window->x++;
  507.         else
  508.             Window->x += Window->Parms[0];
  509.         Window_Scroll(Window);
  510.         Escflg = ESCAPE_NONE;
  511.         break;
  512.       case 'D':       /* \E[%p1%dD - cub, cub1 */
  513.         if (Window->Parms[0] < 1)
  514.           Window->x--;
  515.         else
  516.             Window->x -= Window->Parms[0];
  517.         Window_Scroll(Window);
  518.         Escflg = ESCAPE_NONE;
  519.         break;
  520.       case 'f':       /* \E[%i%p1%d;%p2%df */
  521.       case 'H':       /* \E[%i%p1%d;%p2%dH - cup */
  522.         Window->x = Window->Parms[1] - 1;
  523.         Window->y = Window->Parms[0] - 1;
  524.         if (Window->x < 0)  Window->x = 0;
  525.         if (Window->x > 79) Window->x = 79;
  526.         if (Window->y < Window->Top)    Window->y = Window->Top;
  527.         if (Window->y > Window->Bottom) Window->y = Window->Bottom;
  528.         bbc_vduq(31, Window->x, Window->y);
  529.         Escflg = ESCAPE_NONE;
  530.         break;
  531.       case 'K':       /* \E[K - e1*/
  532.         switch (Window->Parms[0])
  533.         {
  534.         case -1:
  535.         case  0:
  536.           bbc_vduq(23,8,5,6,0,0,0,0,0,0);
  537.           break;
  538.         case  1:
  539.           bbc_vduq(23,8,4,5,0,0,0,0,0,0);
  540.           break;
  541.         case  2:
  542.           bbc_vduq(23,8,4,6,0,0,0,0,0,0);
  543.           break;
  544.         default:
  545.           Escflg = ESCAPE_NONE;
  546.           break;
  547.         }
  548.         Escflg = ESCAPE_NONE;
  549.         break;
  550.       case 'J':       /* \E[J - ed */
  551.         switch (Window->Parms[0])
  552.         {
  553.         case -1:
  554.         case  0:
  555.           bbc_vduq(23,8,5,10,0,0,0,0,0,0);
  556.           break;
  557.         case  1:
  558.           bbc_vduq(23,8,0,5,0,0,0,0,0,0);
  559.           break;
  560.         case  2:
  561.           bbc_vduq(23,8,0,10,0,0,0,0,0,0);
  562.           break;
  563.         default:
  564.           Escflg = ESCAPE_NONE;
  565.           break;
  566.         }
  567.         Escflg = ESCAPE_NONE;
  568.         break;
  569.       case 'm':       /* \E[nnm - smso, rmso, smul, */
  570.         /*     rmul, bold, rev, blink */
  571.         switch (Window->Parms[0])
  572.         {
  573.         case -1:
  574.         case 0:         /* \E[0m - rmso, rmul */
  575.           Window->Attr = ATTR_NORMAL;
  576.           break;
  577.         case 1:         /* \E[1m - bold */
  578.           Window->Attr = ATTR_BOLD;
  579.           break;
  580.         case 4:         /* \E[4m - smul */
  581.           Window->Attr = ATTR_UNDER;
  582.           break;
  583.         case 5:         /* \E[5m - blink */
  584.           Window->Attr = ATTR_BLINK;
  585.           break;
  586.         case 7:         /* \E[7m - smso, rev */
  587.           Window->Attr = ATTR_REVERSE;
  588.           break;
  589.         default:
  590.           break;
  591.         }
  592.         Escflg = ESCAPE_NONE;
  593.         break;
  594.       case 'L':       /* \E[L - il1 */
  595.         if (Window->Parms[0] < 1) Window->Parms[0] = 1;
  596.         bbc_vduq(28, 0, Window->Bottom, 79, Window->y);
  597.         for (i = 0; i < Window->Parms[0]; i++)
  598.           bbc_vduq(23,7,0,2,0,0,0,0,0,0); 
  599.         bbc_vduq(28,0,Window->Bottom,79,Window->Top);
  600.         bbc_vduq(31, Window->x, Window->y);
  601.         Escflg = ESCAPE_NONE;
  602.         break;
  603.       case 'M':       /* \E[M - dl1 */
  604.         if (Window->Parms[0] < 1) Window->Parms[0] = 1;                                                
  605.         bbc_vduq(28, 0, Window->Bottom, 79, Window->y);
  606.         for (i = 0; i < Window->Parms[0]; i++)
  607.           bbc_vduq(23,7,0,3,0,0,0,0,0,0); 
  608.         bbc_vduq(28, 0, Window->Bottom, 79, Window->Top);
  609.         bbc_vduq(31, Window->x, Window->y);
  610.         Escflg = ESCAPE_NONE;
  611.         break;
  612.       case 'P':       /* \E[P */
  613.         if (Window->Parms[0] < 1) Window->Parms[0] = 1;
  614.         bbc_vduq(28, Window->x, Window->y, 79, Window->y);
  615.         for (i = 0; i < Window->Parms[0]; i++)
  616.           bbc_vduq(23,7,0,1,0,0,0,0,0,0); 
  617.         bbc_vduq(28, 0, Window->Bottom, 79, Window->Top);
  618.         bbc_vduq(31, Window->x, Window->y);
  619.         Escflg = ESCAPE_NONE;
  620.         break;
  621.       case 'r':       /* \E[r */
  622.         if (Window->Parms[0] < 0)
  623.           Window->Top = 0;
  624.         else
  625.             Window->Top = Window->Parms[0] - 1;
  626.         if (Window->Parms[1] < 0)
  627.           Window->Bottom = 23;
  628.         else
  629.             Window->Bottom = Window->Parms[1] - 1;
  630.         if (Window->Top < 0)  Window->Top = 0;
  631.         if (Window->Top > 22) Window->Top = 22;
  632.         if (Window->Bottom < 1)  Window->Bottom = 23;
  633.         if (Window->Bottom > 23) Window->Bottom = 23;
  634.         Window->x = 0;
  635.         Window->y = Window->Top;
  636.         bbc_vduq(28, 0, Window->Bottom , 79, Window->Top);
  637.         bbc_vduq(31, Window->x, Window->y);
  638.         Escflg = ESCAPE_NONE;
  639.         break;
  640.       case 'h':       /* \E[h - cnorm, cvvis */
  641.         Window->Cursor = 1;
  642.         Escflg = ESCAPE_NONE;
  643.         break;
  644.       case 'l':       /* \E[l - civis */
  645.         Window->Cursor = 0;
  646.         Escflg = ESCAPE_NONE;
  647.         break;
  648.       case 'g':       /* \E[g - tbc */
  649.         if (Window->Parms[0] == 3)
  650.         {
  651.           for (i = 0; i < SCREEN_WIDTH; i++)
  652.             Window->Tabs[i] = ' ';
  653.         }
  654.         else
  655.         {
  656.           if (Window->Parms[0] == 0 || Window->Parms[0] < 0)
  657.             Window->Tabs[Window->x] = ' ';
  658.         }
  659.         Escflg = ESCAPE_NONE;
  660.         break;
  661.       default:
  662.         Escflg = ESCAPE_NONE;
  663.         break;
  664.       }
  665.  
  666.       s++;
  667.       n--;
  668.     }
  669.  
  670.     while ((Escflg == ESCAPE_3) && (n > 0))
  671.     {
  672.       switch (*s)
  673.       {
  674.       case 0x08:
  675.         Window->x--;
  676.         Window_Scroll(Window);
  677.         break;
  678.       case 'A':       /* \E(A */
  679.       case 'B':       /* \E(B - font0 */
  680.       case '1':       /* \E(1 */
  681.         Window->G0 = 0;
  682.         /*
  683.                                                 if (!Window->Charset)
  684.                                                         Window->Attrib = VSnotgraph(Window->Attrib);
  685.         */
  686.         Escflg = ESCAPE_NONE;
  687.         break;
  688.       case '0':       /* \E(0 - font1 */
  689.       case '2':       /* \E(2 */
  690.         Window->G0 = 1;
  691.         /*
  692.                                                 if (!Window->Charset)
  693.                                                         Window->Attrib = VSgraph(Window->Attrib);
  694.         */
  695.         Escflg = ESCAPE_NONE;
  696.         break;
  697.       default:
  698.         Escflg = ESCAPE_NONE;
  699.         break;
  700.       }
  701.  
  702.       s++;
  703.       n--;
  704.     }
  705.  
  706.     while ((Escflg == ESCAPE_4) && (n > 0))
  707.     {
  708.       switch (*s)
  709.       {
  710.       case 0x08:
  711.         Window->x--;
  712.         Window_Scroll(Window);
  713.         break;
  714.       case 'A':       /* \E)A */
  715.       case 'B':       /* \E)B */
  716.       case '1':       /* \E)1 */
  717.         Window->G1 = 0;
  718.         /* if (Window->Charset)
  719.           Window->Attrib = VSnotgraph(Window->Attrib); */
  720.         Escflg = ESCAPE_NONE;
  721.         break;
  722.       case '0':       /* \E)0 */
  723.       case '2':       /* \E)2 */
  724.         Window->G1 = 1;
  725.         /* if (Window->Charset)
  726.            Window->Attrib = VSgraph(Window->Attrib); */
  727.         Escflg = ESCAPE_NONE;
  728.         break;
  729.       default:
  730.         Escflg = ESCAPE_NONE;
  731.         break;
  732.       }
  733.  
  734.       s++;
  735.       n--;
  736.     }
  737.  
  738.     while ((Escflg == ESCAPE_5) && (n > 0))
  739.     {
  740.       switch (*s)
  741.       {
  742.       case 0x08:
  743.         Window->x--;
  744.         Window_Scroll(Window);
  745.         break;
  746.       default:
  747.         Escflg = ESCAPE_NONE;
  748.         break;
  749.       }
  750.  
  751.       s++;
  752.       n--;
  753.     }
  754.     /* if ((Escflg > ESCAPE_1) && (n > 0))
  755.       {
  756.          Escflg = ESCAPE_NONE;
  757.          s++;
  758.          n--;
  759.       } */
  760.   }
  761.  
  762.   Window->Esc_Flag = Escflg;
  763.  
  764.   if (Window->Cursor)
  765.   {
  766.     cx = Window->x * 16;
  767.     cy = 768 - Window->y * 32 - 28;
  768.     bbc_vduq(25, 4,   cx % 256, cx / 256,
  769.     cy % 256, cy / 256);
  770.     bbc_vduq(25, 102, (cx + 16) % 256, (cx + 16) / 256,
  771.     (cy + 24) % 256, (cy + 24) / 256);
  772.   }
  773.  
  774.   Changed_Box(-1, &Box);
  775.  
  776.   if (scale)
  777.   {
  778.     r.w = Window->Window_Handle;
  779.     r.box.x0 = XtoWork(Box->box.x0) * Window->X_Mag_Mult / Window->X_Div_Mult - XtoWork(1);
  780.     r.box.x1 = XtoWork(Box->box.x1) * Window->X_Mag_Mult / Window->X_Div_Mult + XtoWork(1);
  781.     r.box.y0 = YtoWork(Box->box.y0 - SPRITE_HEIGHT) * Window->Y_Mag_Mult / Window->Y_Div_Mult - YtoWork(1);
  782.     r.box.y1 = YtoWork(Box->box.y1 - SPRITE_HEIGHT) * Window->Y_Mag_Mult / Window->Y_Div_Mult + YtoWork(1);
  783.   }
  784.   else
  785.   {
  786.     r.w = Window->Window_Handle;
  787.     r.box.x0 = XtoWork(Box->box.x0) - XtoWork(1);
  788.     r.box.x1 = XtoWork(Box->box.x1) + XtoWork(1);
  789.     r.box.y0 = YtoWork(Box->box.y0 - SPRITE_HEIGHT) - YtoWork(1);
  790.     r.box.y1 = YtoWork(Box->box.y1 - SPRITE_HEIGHT) + YtoWork(1);
  791.   }
  792.  
  793.   sprite_restorestate(State);
  794.  
  795.   Update_Window(Window, r);
  796. }
  797.  
  798. static void Window_Scroll(Terminal *Window)
  799. {
  800.   int i;
  801.  
  802.   Window->y += Window->x / 80;
  803.   Window->x %= 80;
  804.  
  805.   if (Window->y < Window->Top)
  806.   {
  807.     for (i = 0; i < (Window->Top - Window->y); i++)
  808.       bbc_vduq(23, 7, 0, 2, 0, 0, 0, 0, 0, 0);
  809.  
  810.     Window->y = Window->Top;
  811.   }
  812.  
  813.   if (Window->y > Window->Bottom)
  814.   {
  815.     for (i = 0; i < (Window->y - Window->Bottom); i++)
  816.       bbc_vduq(23, 7, 0, 3, 0, 0, 0, 0, 0, 0);
  817.  
  818.     Window->y = Window->Bottom;
  819.   }
  820.  
  821.   bbc_vduq(31, Window->x, Window->y);
  822. }
  823.  
  824. static os_error *Changed_Box(int Flag, change_box **Box)
  825. {
  826.   os_regset r;
  827.   os_error *e;
  828.  
  829.   r.r[0] = Flag;
  830.   e = os_swix(OS_ChangedBox, &r);
  831.   if (e == 0)
  832.     *Box = (change_box *)(r.r[1]);
  833.  
  834.   return(e);
  835. }
  836.  
  837. void Window_Close(Terminal *Window)
  838. {
  839.   wimp_close_wind(Window->Window_Handle);
  840.  
  841.   if (Window->Session != NULL)
  842.   {
  843.     close_sess(Window->Session);
  844.     Window->Session = NULL;
  845.   }
  846.   if (!Window->Flags.flags.dont_destroy)
  847.   {
  848.     if (Window->Record != NULL)
  849.       fclose(Window->Record);
  850.   
  851.     free(Window->Sprite.Area);
  852.     free(Window->Save_Area);
  853.     free(Window);
  854.   }
  855. }
  856. extern struct cmds cmds[];
  857.  
  858. static int keyboard(Terminal *Window, int c)
  859. {
  860.   char Key_Buffer[10];
  861.   int  Key_Length;
  862.  
  863.   if ((Key_Length = keymap(Window->Session ? Window->Session->raw : FALSE, Key_Buffer, c)) == 0)
  864.     return(0);
  865.  
  866.   if (Window->Session == NULL || Window->Session->echo)
  867.     Window_Write(Window, Key_Buffer, Key_Length);      
  868.  
  869.   if (Window->Session && Window->Session->raw)
  870.   {
  871.     (*Window->Session->parse)(Window->Session, Key_Buffer, Key_Length);
  872.   }
  873.   else
  874.   {
  875.     switch (c)
  876.     {
  877.     case '\b':
  878.       if (Window->bufptr > Window->buffer)
  879.         Window->bufptr--;
  880.       break;
  881.     case '\r':
  882.     case '\n':
  883.       if (Window->Session && !Window->Session->echo && Window->Session->parse)
  884.         Window_Write(Window, "\n", 1);
  885.       *Window->bufptr++ = '\r';
  886.       *Window->bufptr++ = '\n';
  887.       if (Window->Session && Window->Session->parse)
  888.       {
  889.         (*Window->Session->parse)(Window->Session, Window->buffer, Window->bufptr - Window->buffer);
  890.       }
  891.       else if (Window->Session == NULL)
  892.       {
  893.         cmdparse(cmds, Window->buffer, (void *) Window);
  894.         Window_Write(Window, "net> ", 5);
  895.       }
  896.       Window->bufptr = Window->buffer;
  897.       break;
  898.     default:
  899.       *Window->bufptr++ = c;
  900.       break;
  901.     }
  902.   }
  903.  
  904.   return(1);
  905. }
  906.  
  907. static void Window_Proc(wimp_eventstr *Event, void *Handle)
  908. {
  909.   int c;
  910.   wimp_caretstr wc;
  911.   Terminal *Window = (Terminal *) Handle;
  912.  
  913.   switch (Event->e)
  914.   {
  915.   case wimp_EREDRAW:
  916.     Redraw_Window(Window, Event->data.o.w);
  917.     break;
  918.   case wimp_EOPEN:
  919.     Open_Window(Window, &Event->data.o);
  920.     break;
  921.   case wimp_ECLOSE:
  922.     Window_Close(Window);
  923.     break;
  924.   case wimp_EBUT:
  925.     if (!Window->Flags.flags.no_input && Event->data.but.m.bbits != wimp_BMID)
  926.     {
  927.       wc.w      = Window->Window_Handle;
  928.       wc.i      = -1;
  929.       wc.height = -1;
  930.       wc.x      = 0;
  931.       wc.y      = 0;
  932.       wc.index  = 0;
  933.       wimp_set_caret_pos(&wc);
  934.     }                     
  935.     break;
  936.   case wimp_EKEY:
  937.     c = Event->data.key.chcode;
  938.     if (!keyboard(Window, c))
  939.       wimp_processkey(c);
  940.     break;
  941.  
  942.  
  943. /*******************************************
  944.  Adam - 17-Feb-94
  945.  Purpose: Catch drag file to windows
  946.  *******************************************/
  947.  
  948.   case wimp_ESEND:
  949.   case wimp_ESENDWANTACK:
  950.     switch (Event->data.msg.hdr.action)
  951.     {
  952.       case wimp_MDATASAVE:
  953.           /* Acknowledge the DataSave message with <wimp$scrap> */
  954.           { wimp_msgstr msg;
  955.             msg.hdr.size = 60;
  956.             msg.hdr.your_ref = Event->data.msg.hdr.my_ref;
  957.             msg.hdr.action = wimp_MDATASAVEOK;
  958.             msg.data.datasaveok.w = Event->data.msg.data.datasave.w;
  959.             msg.data.datasaveok.i = Event->data.msg.data.datasave.i;
  960.             msg.data.datasaveok.x = Event->data.msg.data.datasave.x;
  961.             msg.data.datasaveok.y = Event->data.msg.data.datasave.y;
  962.             msg.data.datasaveok.estsize = -1;
  963.             msg.data.datasaveok.type = Event->data.msg.data.datasaveok.type;
  964.             strcpy(msg.data.datasaveok.name, "<Wimp$Scrap>");
  965.             wimp_sendmessage(wimp_ESEND, &msg, Event->data.msg.hdr.task);
  966.           }
  967.           break;
  968.       case wimp_MDATALOAD:
  969.           Process_Import(Event, Window);
  970.         break;
  971.     }
  972.     break;
  973.  
  974. /*******************************************/
  975.  
  976.   default:
  977.     break;
  978.   }
  979. }
  980.  
  981. Terminal *Window_Open(struct session *Sess, char *Description, unsigned int Flags)
  982. {
  983.   Terminal *Window;
  984.   static int clones = 0;
  985.   int Save_Area_Size;
  986.   sprite_ptr Pointer;
  987.   sprite_state sprite_state;
  988.   wimp_wstate window_state;
  989.   wimp_redrawstr r;
  990.   template *t;
  991.  
  992.   if (term_type != -1)
  993.     return(NULL);
  994.  
  995.   if ((Window = (Terminal *) malloc(sizeof(Terminal))) == NULL)
  996.     return(NULL);
  997.  
  998.   memset(Window, 0, sizeof(Terminal));
  999.  
  1000.   Window->Flags.value = Flags;
  1001.  
  1002.   if ((Window->Sprite.Area = (sprite_area *) malloc(Window->Flags.flags.sixteen ? SPRITE_SIZE_16 :  SPRITE_SIZE_0)) == NULL)
  1003.   {
  1004.     free(Window);
  1005.     return(NULL);
  1006.   }
  1007.  
  1008.   sprite_area_initialise(Window->Sprite.Area, Window->Flags.flags.sixteen ? SPRITE_SIZE_16 :  SPRITE_SIZE_0);
  1009.  
  1010.   sprite_create(Window->Sprite.Area, "screendump", sprite_nopalette, SPRITE_WIDTH, SPRITE_HEIGHT, Window->Flags.flags.sixteen ? 12 : 0);
  1011.  
  1012.   Window->Sprite.id.tag    = sprite_id_name;
  1013.   Window->Sprite.id.s.name = "screendump";
  1014.  
  1015.   sprite_select_rp(Window->Sprite.Area, &Window->Sprite.id, &Pointer);
  1016.  
  1017.   Window->Sprite.id.tag    = sprite_id_addr;
  1018.   Window->Sprite.id.s.addr = Pointer;
  1019.  
  1020.   sprite_sizeof_spritecontext(Window->Sprite.Area, &Window->Sprite.id, &Save_Area_Size);
  1021.  
  1022.   if ((Window->Save_Area = (int *)malloc(Save_Area_Size)) == NULL)
  1023.   {
  1024.     free(Window->Sprite.Area);
  1025.     free(Window);
  1026.     return(NULL);
  1027.   }
  1028.  
  1029.   t = template_copy(template_find("Window"));
  1030.   t->window.box.x0 += 40 * clones;
  1031.   t->window.box.x1 += 40 * clones;
  1032.   t->window.box.y0 -= 40 * clones;
  1033.   t->window.box.y1 -= 40 * clones;
  1034.   clones = ++clones % 5;
  1035.   wimp_create_wind(&t->window, &Window->Window_Handle);
  1036.   win_settitle(Window->Window_Handle, Description);
  1037.  
  1038.   win_register_event_handler(Window->Window_Handle, Window_Proc, (void *) Window);
  1039.  
  1040. /*  Window->Menu = menu_new("Session", ">Info,Kick,Reset,Close");
  1041.   event_attachmenu(Window->Window_Handle, Window->Menu, Window_MenuProc, (void *)Window); */
  1042.   Window->bufptr = Window->buffer;
  1043.  
  1044.   Window->Save_Area[0] = 0;
  1045.  
  1046.   if (Window->Flags.flags.sixteen)
  1047.   {
  1048.     Window->Foreground[ATTR_NORMAL]  = 0;
  1049.     Window->Background[ATTR_NORMAL]  = 8;
  1050.     Window->Foreground[ATTR_REVERSE] = 7;
  1051.     Window->Background[ATTR_REVERSE] = 0;
  1052.     Window->Foreground[ATTR_BOLD]    = 9;
  1053.     Window->Background[ATTR_BOLD]    = 8;
  1054.     Window->Foreground[ATTR_UNDER]   = 10;
  1055.     Window->Background[ATTR_UNDER]   = 8;
  1056.     Window->Foreground[ATTR_BLINK]   = 11;
  1057.     Window->Background[ATTR_BLINK]   = 8;
  1058.   }
  1059.   else
  1060.   {
  1061.     Window->Foreground[ATTR_NORMAL]  = 0;
  1062.     Window->Background[ATTR_NORMAL]  = 1;
  1063.     Window->Foreground[ATTR_REVERSE] = 1;
  1064.     Window->Background[ATTR_REVERSE] = 0;
  1065.     Window->Foreground[ATTR_BOLD]    = 0;
  1066.     Window->Background[ATTR_BOLD]    = 1;
  1067.     Window->Foreground[ATTR_UNDER]   = 0;
  1068.     Window->Background[ATTR_UNDER]   = 1;
  1069.     Window->Foreground[ATTR_BLINK]   = 0;
  1070.     Window->Background[ATTR_BLINK]   = 1;
  1071.   }
  1072.  
  1073.   sprite_outputtosprite(Window->Sprite.Area, &Window->Sprite.id, Window->Save_Area, &sprite_state);
  1074.  
  1075.   Window_Reset(Window);
  1076.  
  1077.   sprite_restorestate(sprite_state);
  1078.  
  1079.   Window->Session  = Sess;
  1080.   if (Sess)
  1081.     Window->Session->keypad = 0;
  1082.   else
  1083.     Window->keypad = 0;
  1084.  
  1085.   if (!Window->Flags.flags.dont_open)
  1086.   {
  1087.     wimp_get_wind_state(Window->Window_Handle, &window_state);
  1088.     window_state.o.behind = -1;
  1089.     Open_Window(Window, &window_state.o);
  1090.  
  1091.     if (Window->Flags.flags.caret)
  1092.     {
  1093.       wimp_caretstr wc;
  1094.       
  1095.       wc.w      = Window->Window_Handle;
  1096.       wc.i      = -1;
  1097.       wc.height = -1;
  1098.       wc.x      = 0;
  1099.       wc.y      = 0;
  1100.       wc.index  = 0;
  1101.       wimp_set_caret_pos(&wc);
  1102.     }
  1103.     r.w      = Window->Window_Handle;
  1104.     r.box.x0 =  0;
  1105.     r.box.x1 =  XtoWork(SPRITE_WIDTH);
  1106.     r.box.y0 = -YtoWork(SPRITE_HEIGHT);
  1107.     r.box.y1 =  0;
  1108.     wimp_force_redraw(&r);
  1109.   }
  1110.   return(Window);
  1111. }
  1112.  
  1113. /*******************************************
  1114.  Adam - 17-Feb-94
  1115.  Purpose: Process drag file to windows
  1116.  
  1117.  This routine processes files dragged to one
  1118.  of the terminal windows and processes it as follows:
  1119.  
  1120.  Drags to FTP session are converted to "put <pathname> <leafname>"
  1121.  Drags to main window are convert to "source <pathname>"
  1122.  
  1123.  In this implementation, no use has been made of in-core transfers
  1124.  as they arn't really need for this, except perhaps when dragging
  1125.  in from from !Edit, even then they will probably need reading
  1126.  line by line - eg when I've added auto login to an ftp
  1127.  or telnet site.
  1128.  
  1129.  *******************************************/
  1130.  
  1131. static void Process_Import(wimp_eventstr *Event, Terminal *Window)
  1132. {
  1133.   os_error *e;
  1134.   os_filestr f;
  1135.  
  1136.   int filesize;
  1137.   int filetype;
  1138.   char *filename;
  1139.  
  1140.   char command[256];
  1141.  
  1142.   filetype = xferrecv_checkinsert(&filename);
  1143.   xferrecv_insertfileok();
  1144.  
  1145.   *command = '\0'; /* No command present - yet! */
  1146.  
  1147.   if (filetype <= 0x1000)
  1148.   {
  1149.     f.action = 5; /* Get file size */
  1150.     f.name = filename;
  1151.     e = wimpt_complain(os_file(&f));
  1152.     filesize = f.start;
  1153.  
  1154.     /* If the file has been dragged to the main window and it is a text file, source it! */
  1155.  
  1156.     if (Window->Session==NULL && filetype==0xfff /* Text file */)
  1157.     {
  1158.       sprintf(command, "source %s\n", filename);
  1159.  
  1160.     }
  1161.     else if (Window->Session->type==FTP)
  1162.     {
  1163.  
  1164.     /* if FTP then do a put (will extend this to a dbox to allow remote name to be set */
  1165.  
  1166.       sprintf(command, "put %s %s\n", filename, leafname(filename));
  1167.     }
  1168.  
  1169.     /* Send the command (if any) to the appropriate parser */
  1170.  
  1171.     if (*command!='\0')
  1172.     {
  1173.  
  1174.       /* I have sort of copied this from key handler above... ??? */
  1175.  
  1176.       if (Window->Session == NULL || Window->Session->echo)
  1177.         Window_Write(Window, command, strlen(command));      
  1178.  
  1179.       if (Window->Session && Window->Session->parse)
  1180.         (*Window->Session->parse)(Window->Session, command, strlen(command));
  1181.       else if (Window->Session == NULL)
  1182.         cmdparse(cmds, command, (void *) Window);
  1183.     }
  1184.  
  1185.   }
  1186. }
  1187.  
  1188. /* Given a RiscOS pathname, return pointer to leafname */
  1189. static char *leafname(char *s)
  1190. {
  1191.   char *p;
  1192.   p = s+strlen(s);
  1193.   while (p>s && *p!='.' && *p!=':')
  1194.     p -= 1;
  1195.   return (p==s)?(p):(p+1);
  1196. }
  1197.  
  1198.  
  1199.